﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ImportMFGsFromFile.CApIMFFCSVParser
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using DnProcessSimulateCommands.ImportMFGsFromFile.Resources;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;


namespace DnProcessSimulateCommands.ImportMFGsFromFile;

public class CApIMFFCSVParser
{
  public static readonly char DELIMITER = CultureInfo.CurrentCulture.TextInfo.ListSeparator[0];
  public const char GROUPSYMBOL = '"';
  private const char ATTRIBUTES_DELIMITER = '_';
  private static Dictionary<CSVFileColumnHeaders, List<KeyValuePair<int, string>>> headerDictionary;
  private HashSet<string> duplicateColumnHeaders;
  private HashSet<string> columnHeadersSet;
  private readonly string[] mustHaveColumnHeaders = new string[4]
  {
    "name",
    "x",
    "y",
    "z"
  };
  private OnLineParsedEventHandler OnLineParsedP;
  private OnParsingProblemEventHandler OnParsingProblemP;

  public CApIMFFCSVParser()
  {
    CApIMFFCSVParser.headerDictionary = new Dictionary<CSVFileColumnHeaders, List<KeyValuePair<int, string>>>();
    this.columnHeadersSet = new HashSet<string>();
    this.duplicateColumnHeaders = new HashSet<string>();
  }

  public bool ParseCSVFile(string filenamePath)
  {
    bool csvFile = true;
    try
    {
      using (StreamReader streamReader = new StreamReader(filenamePath))
      {
        int i = 1;
        if (!this.InitializeHeaderDictionary(streamReader.ReadLine()))
          csvFile = false;
        if (csvFile)
        {
          while (!streamReader.EndOfStream)
          {
            string line = streamReader.ReadLine();
            ++i;
            try
            {
              if (line.Trim() != "")
              {
                string[] csvLine = CApIMFFCSVParser.ParseCSVLine(line);
                this.CheckLocation(csvLine);
                this.FireOnLineParsed(filenamePath, csvLine, i);
                this.CheckRotation(csvLine);
              }
            }
            catch (CApIMFFCSVParser.LocationException ex)
            {
              this.FireOnParsingProblem(IMFFLogCode.INVALID_LOCATION, string.Format(IMFFResources.IMFF_INVALID_LOCATION_FORMAT, (object) i, (object) ex.Name, (object) ex.X, (object) ex.Y, (object) ex.Z));
            }
            catch (CApIMFFCSVParser.RotationException ex)
            {
              this.FireOnParsingProblem(IMFFLogCode.INVALID_ROTATION, string.Format(IMFFResources.IMFF_INVALID_ROTATION_FORMAT, (object) i, (object) ex.Name, (object) ex.RX, (object) ex.RY, (object) ex.RZ));
            }
            catch (Exception ex)
            {
              this.FireOnParsingProblem(IMFFLogCode.CANNOT_PARSE_LINE, string.Format(IMFFResources.IMFF_CREATION_FAILED_FORMAT, (object) i, (object) line));
            }
          }
        }
      }
    }
    catch (IOException ex)
    {
      this.FireOnParsingProblem(IMFFLogCode.FILE_CANNOT_BE_OPENED, string.Format(IMFFResources.IMFF_IO_EXCEPTION, (object) filenamePath));
      csvFile = false;
    }
    return csvFile;
  }

  public static Dictionary<CSVFileColumnHeaders, List<KeyValuePair<int, string>>> HeaderColumnsMapping
  {
    get => CApIMFFCSVParser.headerDictionary;
  }

  internal event OnLineParsedEventHandler OnLineParsed
  {
    add => this.OnLineParsedP += value;
    remove => this.OnLineParsedP -= value;
  }

  public event OnParsingProblemEventHandler OnParsingProblem
  {
    add => this.OnParsingProblemP += value;
    remove => this.OnParsingProblemP -= value;
  }

  private static string DoubleGroupSymbol
  {
    get => new string(new char[2]{ '"', '"' });
  }

  private static string SingleGroupSymbol
  {
    get => new string(new char[1]{ '"' });
  }

  private void FireOnLineParsed(string filePath, string[] parsedLine, int i)
  {
    if (this.OnLineParsedP == null)
      return;
    this.OnLineParsedP((object) this, new OnLineParsedEventArgs(filePath, parsedLine, i));
  }

  private void FireOnParsingProblem(IMFFLogCode res, string message)
  {
    if (this.OnParsingProblemP == null)
      return;
    this.OnParsingProblemP((object) this, new OnParsingProblemEventArgs(res, message));
  }

  private bool InitializeHeaderDictionary(string line)
  {
    CApIMFFCSVParser.headerDictionary.Clear();
    this.columnHeadersSet.Clear();
    this.duplicateColumnHeaders.Clear();
    bool flag = true;
    string[] csvLine = CApIMFFCSVParser.ParseCSVLine(line);
    for (int index = 0; index < csvLine.Length; ++index)
    {
      string cn = csvLine[index].Trim();
      flag &= this.CheckMultipleColumns(cn);
      if (flag)
      {
        if (cn.Equals("name", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.NAME, index);
        else if (cn.Equals("x", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.X, index);
        else if (cn.Equals("y", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.Y, index);
        else if (cn.Equals("z", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.Z, index);
        else if (cn.Equals("leading part", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.LEADING_PART, index);
        else if (cn.Equals("connected part", StringComparison.CurrentCultureIgnoreCase))
        {
          if (!CApIMFFCSVParser.headerDictionary.ContainsKey(CSVFileColumnHeaders.CONNECTED_PARTS))
            this.AddListToHeaderDicitionary(CSVFileColumnHeaders.CONNECTED_PARTS, index, true);
          CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.CONNECTED_PARTS].Add(new KeyValuePair<int, string>(index, (string) null));
        }
        else if (cn.StartsWith("attribute_", StringComparison.CurrentCultureIgnoreCase))
        {
          int num = cn.IndexOf('_');
          string str = cn.Substring(num + 1);
          if (!CApIMFFCSVParser.headerDictionary.ContainsKey(CSVFileColumnHeaders.ATTRIBUTES))
            this.AddListToHeaderDicitionary(CSVFileColumnHeaders.ATTRIBUTES, index, true);
          CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.ATTRIBUTES].Add(new KeyValuePair<int, string>(index, str));
        }
        else if (cn.Equals("class", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.CLASS, index);
        else if (cn.Equals("rx", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.RX, index);
        else if (cn.Equals("ry", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.RY, index);
        else if (cn.Equals("rz", StringComparison.CurrentCultureIgnoreCase))
          this.AddListToHeaderDicitionary(CSVFileColumnHeaders.RZ, index);
        else
          this.FireOnParsingProblem(IMFFLogCode.COLUMN_NOT_USED, $"\"{cn}\"");
      }
    }
    if (!flag)
      this.FireDuplicateColumns();
    return flag & this.CheckColumnsExistance();
  }

  private void FireDuplicateColumns()
  {
    string str = "";
    int num = 0;
    HashSet<string>.Enumerator enumerator = this.duplicateColumnHeaders.GetEnumerator();
    while (enumerator.MoveNext())
    {
      str = $"{str}\"{enumerator.Current}\"";
      if (num++ < this.duplicateColumnHeaders.Count - 1)
        str += ", ";
    }
    this.FireOnParsingProblem(IMFFLogCode.MULTIPLE_COLUMNS, string.Format(IMFFResources.IMFF_MULTIPLE_COLUMNS, (object) str));
  }

  private bool CheckMultipleColumns(string cn)
  {
    bool flag = true;
    if (!this.columnHeadersSet.Contains(cn.ToLower()))
      this.columnHeadersSet.Add(cn.ToLower());
    else if (!cn.Equals("connected part", StringComparison.CurrentCultureIgnoreCase))
    {
      flag = false;
      this.duplicateColumnHeaders.Add(cn.ToLower());
    }
    return flag;
  }

  private bool CheckColumnsExistance()
  {
    bool flag = true;
    string str = "";
    for (int index = 0; index < this.mustHaveColumnHeaders.Length; ++index)
    {
      if (!this.columnHeadersSet.Contains(this.mustHaveColumnHeaders[index]))
        str = $"{str}\"{this.mustHaveColumnHeaders[index]}\", ";
    }
    if (str != "")
    {
      this.FireOnParsingProblem(IMFFLogCode.MISSING_COLUMN_HEADER, string.Format(IMFFResources.IMFF_MISSING_COLUMN_HEADER, (object) str.Substring(0, str.Length - 2)));
      flag = false;
    }
    return flag;
  }

  private void AddListToHeaderDicitionary(
    CSVFileColumnHeaders columnHeader,
    int columnIndex,
    bool emptyList = false)
  {
    KeyValuePair<int, string> keyValuePair = new KeyValuePair<int, string>(columnIndex, (string) null);
    List<KeyValuePair<int, string>> keyValuePairList = new List<KeyValuePair<int, string>>();
    if (!emptyList)
      keyValuePairList.Add(keyValuePair);
    CApIMFFCSVParser.headerDictionary.Add(columnHeader, keyValuePairList);
  }

  private void CheckLocation(string[] parsedLine)
  {
    bool flag = false;
    List<KeyValuePair<int, string>> header1 = CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.X];
    List<KeyValuePair<int, string>> header2 = CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.Y];
    List<KeyValuePair<int, string>> header3 = CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.Z];
    double result;
    KeyValuePair<int, string> keyValuePair;
    string x;
    if (!double.TryParse(parsedLine[header1[0].Key], out result))
    {
      string[] strArray = parsedLine;
      keyValuePair = header1[0];
      int key = keyValuePair.Key;
      x = strArray[key];
      flag = true;
    }
    else
      x = result.ToString();
    string[] strArray1 = parsedLine;
    keyValuePair = header2[0];
    int key1 = keyValuePair.Key;
    string y;
    if (!double.TryParse(strArray1[key1], out result))
    {
      string[] strArray2 = parsedLine;
      keyValuePair = header2[0];
      int key2 = keyValuePair.Key;
      y = strArray2[key2];
      flag = true;
    }
    else
      y = result.ToString();
    string[] strArray3 = parsedLine;
    keyValuePair = header3[0];
    int key3 = keyValuePair.Key;
    string z;
    if (!double.TryParse(strArray3[key3], out result))
    {
      string[] strArray4 = parsedLine;
      keyValuePair = header3[0];
      int key4 = keyValuePair.Key;
      z = strArray4[key4];
      flag = true;
    }
    else
      z = result.ToString();
    if (flag)
    {
      string[] strArray5 = parsedLine;
      keyValuePair = CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.NAME][0];
      int key5 = keyValuePair.Key;
      throw new CApIMFFCSVParser.LocationException(strArray5[key5], x, y, z);
    }
  }

  private void CheckRotation(string[] parsedLine)
  {
    bool flag = false;
    bool columnHeaderFound = false;
    string rx;
    if (!this.TryGetDoubleValueFromTable(CSVFileColumnHeaders.RX, parsedLine, ref columnHeaderFound, out rx))
      flag = true;
    string ry;
    if (!this.TryGetDoubleValueFromTable(CSVFileColumnHeaders.RY, parsedLine, ref columnHeaderFound, out ry))
      flag = true;
    string rz;
    if (!this.TryGetDoubleValueFromTable(CSVFileColumnHeaders.RZ, parsedLine, ref columnHeaderFound, out rz))
      flag = true;
    if (columnHeaderFound & flag)
      throw new CApIMFFCSVParser.RotationException(parsedLine[CApIMFFCSVParser.headerDictionary[CSVFileColumnHeaders.NAME][0].Key], rx, ry, rz);
  }

  private static string RemoveQuotesIfNeeded(string current)
  {
    if (current.Contains<char>(CApIMFFCSVParser.DELIMITER))
    {
      if (current.StartsWith(CApIMFFCSVParser.DoubleGroupSymbol))
        return current.Replace(CApIMFFCSVParser.DoubleGroupSymbol, CApIMFFCSVParser.SingleGroupSymbol);
      if (current.StartsWith(CApIMFFCSVParser.SingleGroupSymbol))
        return current.Replace(CApIMFFCSVParser.SingleGroupSymbol, "");
    }
    return current;
  }

  private static string[] ParseCSVLine(string line)
  {
    List<string> stringList = new List<string>();
    if (line == null || line.Length == 0)
      return stringList.ToArray();
    bool flag = false;
    string oldValue = new string(new char[2]{ '"', '"' });
    string newValue = new string(new char[1]{ '"' });
    char[] charArray = line.ToCharArray();
    try
    {
      int num1;
      int num2 = num1 = 0;
      int startIndex = num1;
      int index;
      for (index = num1; index < charArray.Length; ++index)
      {
        if ((int) charArray[index] == (int) CApIMFFCSVParser.DELIMITER)
        {
          if (!flag)
          {
            if (startIndex == num2)
              num2 = index;
            stringList.Add(line.Substring(startIndex, num2 - startIndex).Replace(oldValue, newValue));
            num2 = startIndex = index + 1;
          }
        }
        else if (charArray[index] == '"')
        {
          if (!flag)
          {
            num2 = startIndex = index + 1;
            flag = !flag;
          }
          else if (index + 1 < charArray.Length && charArray[index + 1] == '"')
          {
            ++index;
          }
          else
          {
            num2 = index;
            flag = !flag;
          }
        }
      }
      if (startIndex == num2)
        num2 = index;
      string str = line.Substring(startIndex, num2 - startIndex).Replace(oldValue, newValue);
      if (str.Trim() != "")
        stringList.Add(str);
    }
    catch (Exception ex)
    {
      throw new Exception(line);
    }
    return stringList.ToArray();
  }

  private bool TryGetDoubleValueFromTable(
    CSVFileColumnHeaders columnHeader,
    string[] row,
    ref bool columnHeaderFound,
    out string value)
  {
    bool doubleValueFromTable = false;
    value = "";
    List<KeyValuePair<int, string>> keyValuePairList;
    if (CApIMFFCSVParser.headerDictionary.TryGetValue(columnHeader, out keyValuePairList))
    {
      columnHeaderFound = true;
      if (keyValuePairList[0].Key < ((IEnumerable<string>) row).Count<string>())
      {
        string s = row[keyValuePairList[0].Key];
        double result;
        if (double.TryParse(s, out result))
        {
          value = result.ToString();
          doubleValueFromTable = true;
        }
        else
          value = s;
      }
    }
    return doubleValueFromTable;
  }

  private class LocationException : Exception
  {
    public LocationException(string name, string x, string y, string z)
    {
      this.Name = name;
      this.X = x;
      this.Y = y;
      this.Z = z;
    }

    public string Name { get; private set; }

    public string X { get; private set; }

    public string Y { get; private set; }

    public string Z { get; private set; }
  }

  private class RotationException : Exception
  {
    public RotationException(string name, string rx, string ry, string rz)
    {
      this.Name = name;
      this.RX = rx;
      this.RY = ry;
      this.RZ = rz;
    }

    public string Name { get; private set; }

    public string RX { get; private set; }

    public string RY { get; private set; }

    public string RZ { get; private set; }
  }
}
